﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
using TTLL.Text;
using TTLL.Text.Range;
using TTLL.Text.Ruler;

namespace TTLang.Test.WordBreak
{
    [TestClass]
    public class Test_WordBreak2_RuleCustom
    {
        [TestMethod]
        //这个测试的目的是通过定义规则来匹配词，你问我为什么不用正则直接搞？为了正义
        public void WordRule()
        {
            var rangeNum = new Range_List("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            var rangePoint = new Range_List(".");
            var rangeEmpty = new Range_List(" ", "\t");
            var rangeEnter = new Range_List("\n");


            //这条规则的意思是, 由一个数字开头,然后由不定数量个数字组成
            var rule = new WordRule("number", rangeNum, '1', rangeNum, '*');
            //1个数字开头，若干个数字，1个小数点，之后又是若干个数字like 1.0 1324.2345
            var rule2 = new WordRule("number", rangeNum, '1', rangeNum, '*', rangePoint, '1', rangeNum, '1', rangeNum, '*');
            var rule3 = new WordRule("space", rangeEmpty, '*');

            var teststring = "123.45";

            var w = rule.Scan(teststring, 0);
            Assert.IsTrue(w.text == "123");
            var w2 = rule2.Scan(teststring, 0);
            Assert.IsTrue(w2.text == "123.45");

            var w3 = rule3.Scan(teststring, 0);
            Assert.IsTrue(w3 == null);


            var wstr = "11 22 1324.33 33";
            for (var i = 0; i < wstr.Length;)
            {
                var mw1 = rule.Scan(wstr, i);
                var mw2 = rule2.Scan(wstr, i);
                var mw3 = rule3.Scan(wstr, i);
                Word fw = mw1;
                if (mw2 != null && (fw == null || mw2.posend > fw.posend))
                    fw = mw2;
                if (mw3 != null && (fw == null || mw2.posend > fw.posend))
                    fw = mw3;
                Console.WriteLine("get word:" + fw.wordtype + "  " + fw.text);
                i = fw.posend;
            }
        }
        [TestMethod]

        public void Scanner()
        {
            var rangeNum = new Range_List("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            var rangePoint = new Range_List(".");
            var rangeEmpty = new Range_List(" ", "\t");
            var rangeEnter = new Range_List("\n");

            var rangeLetter = new Range_Letter();//这个集合表示所有的字母
            var letterandnum = new Range_Mix(new IElementRange[] { rangeLetter, rangeNum });

            //为啥不用正则表达式，自己写的好移植，将来小霸王也能用的

            //这条规则的意思是, 由一个数字开头,然后由不定数量个数字组成
            var rule = new WordRule("number", rangeNum, '1', rangeNum, '*');
            //1个数字开头，若干个数字，1个小数点，之后又是若干个数字like 1.0 1324.2345
            var rule2 = new WordRule("number", rangeNum, '1', rangeNum, '*', rangePoint, '1', rangeNum, '1', rangeNum, '*');
            //若干个空格
            var rule3 = new WordRule("space", rangeEmpty, '*');
            //字母开头，之后若干个 字母或数字
            var rule4 = new WordRule("id", rangeLetter, '1', letterandnum, '*');

            var breaker = new WordBreaker();
            breaker.AddRule(rule);
            breaker.AddRule(rule2);
            breaker.AddRule(rule3);
            breaker.AddRule(rule4);

            var wstr = "11 22 1324.33 33 abc12345";

            var words = breaker.Split(wstr);
            foreach (var w in words)
            {
                Console.WriteLine(w.ToString());
            }
        }
        [TestMethod]
        public void ScannerEnter()
        {
            //所有字符
            var rangeALL = new Range_AllChar();

            var rangeNum = new Range_List("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            var rangeEmpty = new Range_List(" ", "\t");
            var rangeEnter = new Range_List("\n","\r\n");

            //这条规则的意思是, 由一个数字开头,然后由不定数量个数字组成
            var rule = new WordRule("number", rangeNum, '1', rangeNum, '*');
            //若干个空格
            var rule3 = new WordRule("space", rangeEmpty, '1', rangeEmpty, '*');
            //新行规则
            var rule5 = new WordRule("newline", rangeEnter, '1', rangeEnter, '*');

            var breaker = new TTLL.Text.WordBreaker();
            breaker.AddRule(rule);
            breaker.AddRule(rule3);
            breaker.AddRule(rule5);
            //breaker.AddRule(rule8);

            var wstr = @"
11 22 
1324
";


            var words = breaker.Split(wstr);
            foreach (var w in words)
            {
                Console.WriteLine(w.ToString());
            }

        }
        [TestMethod]
        public void ScannerWithEnter()
        {
            //所有字符
            var rangeALL = new Range_AllChar();

            var rangeNum = new Range_List("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            var rangePoint = new Range_List(".");
            var rangeEmpty = new Range_List(" ", "\t");
            var rangeEnter = new Range_List("\r\n","\n");

            var rangeCommentStart = new Range_List("/*");
            var rangeCommentEnd = new Range_List("*/");

            var rangestringtag = new Range_List("\"");
            var rangestringspec = new Range_List("\\\\", "\\\"");
            //这个范围表示 所有字符，外加stringspec 通配符 但是排除掉回车不行
            var rangetextinstring = new Range_Mix(new IElementRange[] { rangeALL, rangestringspec }, new IElementRange[] { rangeEnter });

            var rangeLetter = new Range_Letter();//这个集合表示所有的字母
            var letterandnum = new Range_Mix(new IElementRange[] { rangeLetter, rangeNum });

            //为啥不用正则表达式，自己写的好移植，将来小霸王也能用的

            //这条规则的意思是, 由一个数字开头,然后由不定数量个数字组成
            var rule = new WordRule("number", rangeNum, '1', rangeNum, '*');
            //1个数字开头，若干个数字，1个小数点，之后又是若干个数字like 1.0 1324.2345
            var rule2 = new WordRule("number", rangeNum, '1', rangeNum, '*', rangePoint, '1', rangeNum, '1', rangeNum, '*');
            //若干个空格
            var rule3 = new WordRule("space", rangeEmpty, '*');
            //字母开头，之后若干个 字母或数字
            var rule4 = new WordRule("id", rangeLetter, '1', letterandnum, '*');

            //新行规则
            var rule5 = new WordRule("newline", rangeEnter, '*');

            //多行注释规则
            var rule6 = new WordRule("comment", rangeCommentStart, '1', rangeALL, '*', rangeCommentEnd, '1');

            //字符串规则,字符串规则要两份，因为单规则有个未尽的问题\" 会先匹配到字符串结束，用两条规则就可以避免
            var rule7 = new WordRule("string", rangestringtag, '1', rangetextinstring, '*', rangestringtag, '1');
            var rule8 = new WordRule("string", rangestringtag, '1', rangetextinstring, '1', rangetextinstring, '*', rangestringtag, '1');



            var breaker = new TTLL.Text.WordBreaker();
            breaker.AddRule(rule);
            breaker.AddRule(rule2);
            breaker.AddRule(rule3);
            breaker.AddRule(rule4);
            breaker.AddRule(rule5);
            breaker.AddRule(rule6);
            breaker.AddRule(rule7);
            //breaker.AddRule(rule8);

            var wstr = @"/*
    line1
    line2
    this is a comment
*/
            ""adfasdf\""""
11 22 
1324.33 33 abc12345 
";


            var words = breaker.Split(wstr);
            foreach (var w in words)
            {
                Console.WriteLine(w.ToString());
            }
        }


    }
}
